package com.junmeng.lib.acrash

import android.os.Environment
import android.util.Log
import java.io.*
import java.text.DateFormat
import java.text.SimpleDateFormat
import java.util.*
import kotlin.system.exitProcess

class ACrashHandler : Thread.UncaughtExceptionHandler {
    //系统默认的UncaughtException处理类
    private var mDefaultHandler: Thread.UncaughtExceptionHandler? = null
    val TAG = ACrashHandler::class.java.simpleName
    private var mLogPath: String? = null

    //用于格式化日期,作为日志文件名的一部分
    private val formatter: DateFormat = SimpleDateFormat("yyyy-MM-dd-HH-mm-ss")

    /** 保证只有一个CrashHandler实例  */
    private constructor()

    companion object {
        //CrashHandler实例
        private val INSTANCE: ACrashHandler = ACrashHandler()

        /** 获取CrashHandler实例 ,单例模式  */
        fun getInstance(): ACrashHandler {
            return INSTANCE
        }
    }

    fun init(logPath: String) {
        mLogPath = logPath
        //获取系统默认的UncaughtException处理器
        mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler()
        //设置该CrashHandler为程序的默认处理器
        Thread.setDefaultUncaughtExceptionHandler(this)
    }

    override fun uncaughtException(t: Thread, e: Throwable) {
        Log.i("123456", "1111")
        if (!handleException(e) && mDefaultHandler != null) {
            //如果用户没有处理则让系统默认的异常处理器来处理
            mDefaultHandler?.uncaughtException(t, e)
        } else {
            try {
                Thread.sleep(3000)
            } catch (e: InterruptedException) {
            }
            //退出程序
            android.os.Process.killProcess(android.os.Process.myPid())
            exitProcess(1)
        }
    }

    private fun handleException(e: Throwable): Boolean {
        saveCrashInfo2File(e)
        return true

    }

    private fun saveCrashInfo2File(ex: Throwable): String? {
        val sb = StringBuffer()
//        for ((key, value) in infos.entrySet()) {
//            sb.append("$key=$value\n")
//        }
        val writer: Writer = StringWriter()
        val printWriter = PrintWriter(writer)
        ex.printStackTrace(printWriter)
        var cause = ex.cause
        while (cause != null) {
            cause.printStackTrace(printWriter)
            cause = cause.cause
        }
        printWriter.close()
        val result: String = writer.toString()
        sb.append(result)
        try {
            val timestamp = System.currentTimeMillis()
            val time: String = formatter.format(Date())
            val fileName = "crash-$time-$timestamp.log"
            if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
                val path = mLogPath
                val dir = File(path)
                if (!dir.exists()) {
                    dir.mkdirs()
                }
                val fos = FileOutputStream(File(path, fileName))
                fos.write(sb.toString().toByteArray())
                fos.close()
            }
            return fileName
        } catch (e: Exception) {
            Log.e(TAG, "an error occured while writing file...", e)
        }
        return null
    }


}